home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / mscheap2 / packdemo.c < prev    next >
C/C++ Source or Header  |  1990-03-13  |  5KB  |  190 lines

  1. //
  2. //     Copyright (c) 1990 by Optimal Software, All Rights Reserved
  3. //
  4.  
  5. //
  6. //    A demonstration of the heap packing functions _relocate() and _heappack()
  7. //
  8. //    1. Allocate random chunks until out of memory.
  9. //    2. Free a percentage of the chunks (optional command line parameter)
  10. //    3. Relocate the remaining chunks until nothing moves
  11. //    4. Release memory to DOS
  12. //
  13. //    Usage: PACKDEMO [percent_to_free]
  14. //
  15. //           The default for the percent_to_free is 50.
  16. //
  17. //    An interesting variation is to reverse the order of the relocation
  18. //    scan to see what effect it has on the number of passes needed to
  19. //    fully compress the heap.  It appears that a high-to-low pass usually
  20. //    requires multiple passes, while a low-to-high pass has only a small
  21. //    chance of needing more than 1 pass to fully compress the heap.  Also
  22. //    the upward scan seems to produce signifigantly higher packing factors
  23. //    than the downward scan.  These effects are independent of the heap
  24. //    usage factor (percent of free heap memory -- command line parameter).
  25. //
  26.  
  27. #define FALSE 0
  28. #define TRUE (!FALSE) 
  29.  
  30. #define VERBOSE FALSE     /* set TRUE to get detailed before/after heap dumps */
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34.  
  35. #include <heap.h>
  36.  
  37. int main( int argc, char *argv[] )
  38. {
  39. typedef struct tag
  40.    {
  41.    struct tag far *next;
  42.    struct tag far *last;
  43.    } NODE;
  44.  
  45. NODE prealloc, far *head = &prealloc, far *tmp, far *scan;
  46.  
  47. int dispose = 50, count = 0, status;
  48.  
  49. if (argc > 1)
  50.  
  51.    dispose = atoi( argv[1] );      /* percent to deallocate */
  52.  
  53. srand(12345);
  54.  
  55. //
  56. //    Init linked list
  57. //
  58. head->next = head;
  59. head->last = head;
  60.  
  61. //
  62. //    Add entries to the list until malloc() fails
  63. //
  64. //    This code builds the list in order of increasing address
  65. //
  66. while ( ( tmp = _fmalloc( sizeof(NODE) + (rand() % 1000) ) ) != NULL )
  67.    {
  68.    tmp->next = head;
  69.    tmp->last = head->last;
  70.  
  71.    tmp->next->last = tmp;
  72.    tmp->last->next = tmp;
  73.  
  74.    count++;
  75.    }
  76.  
  77. //
  78. //    Check for errors
  79. //
  80. if ( (status = _fheapchk() ) != _HEAPOK)
  81.    {
  82.    printf("Heap error: %s (after allocation sequence)\n", _heapstat( status ) );
  83.  
  84.    _fheapdump( stdout, TRUE );
  85.    }
  86. else
  87.    {
  88.    //
  89.    //    Deallocate a fraction of the allocated entries
  90.    //
  91.    count = (int) ( (long) count * dispose / 100 );
  92.  
  93.    scan = head;
  94.  
  95.    while ( count-- > 0 )
  96.       {
  97.       tmp = scan->next;
  98.  
  99.       if (tmp != head)           /* can't free preallocated node */
  100.          {
  101.          tmp->next->last = tmp->last;
  102.          tmp->last->next = tmp->next;
  103.  
  104.          _ffree( tmp );
  105.          }
  106.  
  107.       do
  108.          {
  109.          scan = scan->next;      /* add some noise to the deallocation sequence */
  110.          }
  111.       while (rand() & 1);
  112.       }
  113.  
  114.    //
  115.    //    Check for errors
  116.    //
  117.    if ( (status = _fheapchk() ) != _HEAPOK)
  118.       {
  119.       printf("Heap error: %s (after deallocation sequence)\n", _heapstat( status ) );
  120.  
  121.       _fheapdump( stdout, TRUE );
  122.       }
  123.    else
  124.       {
  125.       //
  126.       //    Dump the heap prior to packing
  127.       //
  128.       printf("\n*** Before packing\n\n");
  129.  
  130.       _fheapdump( stdout, VERBOSE );
  131.  
  132.       //
  133.       //    Relocate heap entries until nothing moves
  134.       //
  135.       printf("\n*** Relocation passes...\n\n");
  136.  
  137.       do
  138.          {
  139.          count = 0;
  140.  
  141.          scan = head->next;
  142.  
  143.          //
  144.          //    Make a pass through the list attempting to relocate entries
  145.          //
  146.          while (scan != head)
  147.             {
  148.             tmp = _frelocate( scan );
  149.  
  150.             if (tmp != NULL)                /* did it move? */
  151.                {
  152.                scan = tmp;
  153.  
  154.                scan->next->last = scan;     /* send change-of-address to neighbors */
  155.                scan->last->next = scan;
  156.  
  157.                count++;
  158.                }
  159.  
  160.             scan = scan->next;
  161.             }
  162.  
  163.          //
  164.          //    Print results of this pass
  165.          //
  166.          printf("%5u entries relocated; %s\n", count, _heapstat( _fheapchk() ) );
  167.          }
  168.       while (count > 0);
  169.  
  170.       //
  171.       //    Release memory to DOS
  172.       //
  173.       if ( (status = _fheappack() ) != 0)
  174.  
  175.          printf("DOS error %d while packing heap\n", status );
  176.  
  177.       else
  178.          {
  179.          printf("\n*** After packing\n\n");
  180.  
  181.          _fheapdump( stdout, VERBOSE );
  182.  
  183.          printf("Heap status: %s (after packing)\n", _heapstat( _fheapchk() ) );
  184.          }
  185.       }
  186.    }
  187.  
  188. return( 0 );
  189. }
  190.